package com.techchat.backend.controller;

import com.techchat.backend.model.Message;
import com.techchat.backend.service.MessageService;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import java.security.Principal;
import java.util.*;

/**
 * WebSocket 控制器：处理群聊消息和在线用户逻辑
 */
@Controller
public class ChatController {

    private final SimpMessagingTemplate template;
    private final MessageService messageService;

    // 保存当前在线用户名集合
    private final Set<String> onlineSet = Collections.synchronizedSet(new HashSet<>());

    public ChatController(SimpMessagingTemplate template, MessageService messageService) {
        this.template = template;
        this.messageService = messageService;
    }

    /**
     * 处理客户端发送到 /app/chat 的消息，
     * 先保存到数据库，再广播给所有订阅 /topic/public 的客户端。
     */
    @MessageMapping("/chat")
    @SendTo("/topic/public")
    public Message handleChat(@Payload Message msg) {
        // 如果客户端未指定消息类型，默认为用户消息
        // 如果客户端已指定为 IMAGE 或 SYSTEM_NICKNAME_CHANGE，则该类型将被保留
        if (msg.getMessageType() == null) {
            msg.setMessageType(Message.MessageType.USER);
        }
        // 保存新消息到数据库 (包括图片消息，其 content 字段为图片URL)
        messageService.saveMessage(msg);
        // 返回 msg，让 Spring 自动广播到 /topic/public
        return msg;
    }

    /**
     * 处理客户端发送到 /app/online 的消息（用户上线通知）。
     * 将用户名加入在线列表后广播最新在线用户列表到 /topic/onlineUsers。
     */
    @MessageMapping("/online")
    public void handleOnline(@Payload Map<String, String> payload, Principal principal) {
        String username = payload.get("username");
        if (username != null && !username.isEmpty()) {
            onlineSet.add(username);
            // 广播在线用户名单
            template.convertAndSend("/topic/onlineUsers", new ArrayList<>(onlineSet));
        }
    }

    /**
     * 处理客户端发送到 /app/offline 的消息（用户下线通知）。
     */
    @MessageMapping("/offline")
    public void handleOffline(@Payload Map<String, String> payload, Principal principal) {
        String username = payload.get("username");
        if (username != null && !username.isEmpty()) {
            onlineSet.remove(username);
            template.convertAndSend("/topic/onlineUsers", new ArrayList<>(onlineSet));
        }
    }

    /**
     * 监听 SessionDisconnectEvent，当WebSocket会话断开时，
     * 根据 principal.getName() 从在线列表移除并广播新列表。
     */
    @EventListener
    public void handleSessionDisconnect(SessionDisconnectEvent event) {
        Principal principal = event.getUser();
        if (principal != null) {
            String username = principal.getName();
            if (onlineSet.remove(username)) {
                template.convertAndSend("/topic/onlineUsers", new ArrayList<>(onlineSet));
            }
        }
    }
}
